package com.xhwl.centiotdata.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.mq.producer.GeneralProducer;
import com.xhwl.centiotdata.service.IRomaDeviceReceiveService;
import com.xhwl.centiotdata.service.cent.IDeviceCentService;
import com.xhwl.centiotdata.service.integrateconfig.IntegrationConfig;
import com.xhwl.centiotdata.utils.RedisUtils;
import com.xhwl.common.constant.cent.alarm.AlarmConstant;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.device.roma.*;
import com.xhwl.common.enums.CategoryEnum;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.alarm.AlarmManagement;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import com.xhwl.common.query.ToiletQuery;
import com.xhwl.common.query.cent.device.DevicePageQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RomaDeviceReceiveServiceImpl implements IRomaDeviceReceiveService {

    @Autowired
    private IDeviceCentService deviceCentService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private GeneralProducer generalProducer;

    /**
     * 通过roma拿到设备数据进行入库（设备中台）
     * @param devices
     * @param romaConf
     * @return
     */
    public ResultJson receive(List<RomaDeviceDTO> devices, RomaConf romaConf) {
        List<DeviceDTO> deviceDTOS = devices.stream()
                .map(item -> {
                    DeviceDTO deviceDTO = new DeviceDTO();
                    deviceDTO.setProjectId(romaConf.getProjectId());
                    deviceDTO.setIotDeviceId(item.getTerminalId());
                    deviceDTO.setThirdDeviceId(item.getTerminalId());
                    deviceDTO.setName(item.getTerminalName());
                    deviceDTO.setLongitude(item.getLongitude());
                    deviceDTO.setLatitude(item.getLatitude());
                    deviceDTO.setDetailPosition(item.getAddress());
                    deviceDTO.setProductId(romaConf.getProductId());
                    deviceDTO.setCategoryId(romaConf.getCategoryId());
                    if (item.getTerminalTypeIds().equals("[6]")) {
                        // 盥洗室
                        deviceDTO.setDeviceTypeId(45);
                    } else if (item.getTerminalTypeIds().equals("[9]")) {
                        // 红外设备
                        deviceDTO.setDeviceTypeId(41);
                    }
                    if (item.getTerminalStatus() == "NoCommunication") {
                        deviceDTO.setOnlineStatus(0);
                        deviceDTO.setDeviceStatus(4);
                    } else if (item.getTerminalStatus() == "CommunicationOK" || item.getTerminalStatus() == "CheFang") {
                        deviceDTO.setOnlineStatus(1);
                        deviceDTO.setDeviceStatus(1);
                    } else if (item.getTerminalStatus() == "HaveAlarm") {
                        deviceDTO.setOnlineStatus(1);
                        deviceDTO.setDeviceStatus(3);
                    } else if (item.getTerminalStatus() == "HaveSetParm" || item.getTerminalStatus() == "Initial") {
                        deviceDTO.setOnlineStatus(1);
                        deviceDTO.setDeviceStatus(0);
                    } else {
                        deviceDTO.setOnlineStatus(1);
                        deviceDTO.setDeviceStatus(1);
                    }
                    return deviceDTO;
                }).collect(Collectors.toList());
        // 存储设备中台
        deviceCentService.asyncUpdateDevice(deviceDTOS);
        return ResultJson.success();
    }


    /**
     * 设备数据拉取
     * @return
     */
    public void getRomaDevice (DeviceProjSupplierCategory deviceProjSupplierCategory) {
        List<RomaDeviceDTO> list = new ArrayList<>();   
        int pageNo = 1;
        RomaConf romaConf = JSONObject.toJavaObject(deviceProjSupplierCategory.getProperties(), RomaConf.class);
        romaConf.setProjectId(deviceProjSupplierCategory.getProjectId());
        romaConf.setProductId(deviceProjSupplierCategory.getProductId());
        romaConf.setCategoryId(deviceProjSupplierCategory.getProdCategoryId());
        while (true) {
            String result = null;
            RomaDeviceBody romaJson = null;
            try {
                result = getDevice(pageNo, romaConf);
                romaJson = JSONObject.parseObject(result, RomaDeviceBody.class);
                log.info("============================================roma设备请求结果==================================={}", romaJson.getRetCode());
                if ("0".equals(romaJson.getRetCode())) {
                    DataBody dataBody = romaJson.getRetJson().getResult().getData();
                    list.addAll(dataBody.getList());
                    if (pageNo * dataBody.getPageSize() < dataBody.getTotalCount()) {
                        pageNo++;
                    } else {
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        receive(list, romaConf);
    }


    /**
     * 设备数据第三方接口调用（roma）
     * @param pageNo
     * @return
     */
    public String getDevice(int pageNo, RomaConf romaConf) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("pageNo", pageNo);
        jsonObject.put("pageSize", 100);
        jsonObject.put("terminalTypeId", romaConf.getTerminalTypeId());
        String body = HttpUtil.createPost(romaConf.getHttp() + "/iot/v2/devices")
                .header("X-HW-ID", romaConf.getX_HW_ID())
                .header("X-HW-APPKEY", romaConf.getX_HW_APPKEY())
                .body(jsonObject.toJSONString())
                .setConnectionTimeout(3000)
                .setReadTimeout(5000)
                .execute()
                .body();
        return body;
    }


    /**
     * 盥洗室统计数据获取，app调用（透传，未做数据存储）
     * @param toiletQuery
     * @return
     */
    @Override
    public String getToiletRecord(ToiletQuery toiletQuery) {
        // 拉取所有集成配置
        List<DeviceProjSupplierCategory> ToiletConfList = IntegrationConfig.integrationConfigList.stream()
                .filter(integrationConfig -> integrationConfig.getProdCategoryId() == CategoryEnum.TOILET_SYSTEM.getId() && integrationConfig.getProductId() == 21)
                .collect(Collectors.toList());
        if (ToiletConfList.isEmpty()) {
            log.info("集成配置================================={}", ToiletConfList);
            return null;
        }
        RomaConf romaConf = JSONObject.toJavaObject(ToiletConfList.get(0).getProperties(), RomaConf.class);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("gatewayId", toiletQuery.getGatewayId());
        jsonObject.put("terminalId", toiletQuery.getTerminalId());
        jsonObject.put("terminalName", toiletQuery.getTerminalName());
        jsonObject.put("terminalTypeId", toiletQuery.getTerminalTypeId());
        jsonObject.put("areaName", toiletQuery.getAreaName());
        jsonObject.put("buildName", toiletQuery.getBuildName());
        jsonObject.put("unitName", toiletQuery.getUnitName());
        jsonObject.put("pageNo", toiletQuery.getPageNo());
        jsonObject.put("pageSize", toiletQuery.getPageSize());
        String body = HttpUtil.createPost(romaConf.getHttp() + "/iot/v2/device/propertys")
                .header("X-HW-ID", romaConf.getX_HW_ID())
                .header("X-HW-APPKEY", romaConf.getX_HW_APPKEY())
                .body(jsonObject.toJSONString())
                .setConnectionTimeout(3000)
                .setReadTimeout(5000)
                .execute()
                .body();
        return body;
    }


    /**
     * 过滤盥洗室数据进行告警推送，包括空气质量、温度、湿度、氨气值等4种数据
     *
     * 数据记录
     * {
     * 	"data": {
     * 		"pageNo": 1,
     * 		"pageSize": 20,
     * 		"totalCount": 5,
     * 		"totalPage": 1,
     * 		"list": [
     *                        {
     * 				"terminalId": "67",
     * 				"terminalName": "8号楼",
     * 				"propertys": [
     *                    {
     * 						"propertyId": 1,
     * 						"propertyCode": "toiletTotalNum",
     * 						"propertyName": "盥洗室总数",
     * 						"propertyType": "YC",
     * 						"propertyValue": "4",
     * 						"propertyIsAlarm": false,
     * 						"propertyUnit": ""
     *                    },
     * 				]
     *            }
     * 		]
     * 	},
     * 	"code": 200,
     * 	"message": "Success",
     * 	"succeeded": true
     * }
     *
     *
     */
    public ResultJson getToiletDataByTask() {
        // 通过集成配置获取盥洗室配置信息
        List<DeviceProjSupplierCategory> ToiletConfList = IntegrationConfig.integrationConfigList.stream()
                .filter(integrationConfig -> integrationConfig.getProdCategoryId() == CategoryEnum.TOILET_SYSTEM.getId() && integrationConfig.getProductId() == 21)
                .collect(Collectors.toList());
        DeviceProjSupplierCategory deviceProjSupplierCategory = ToiletConfList.get(0);
        if (ToiletConfList.isEmpty()) {
            log.info("集成配置================================={}", ToiletConfList);
            return ResultJson.fail("集成配置信息为空");
        }
        RomaConf romaConf = JSONObject.toJavaObject(deviceProjSupplierCategory.getProperties(), RomaConf.class);
        // 拿到项目id
        Integer projectId = deviceProjSupplierCategory.getProjectId();
        ToiletQuery toiletQuery = new ToiletQuery();
        int pageNo = 1;
        // 接收所有盥洗室属性数据list
        List<ToiletList> list = new ArrayList<>();
        // 通过集成配置属性信息的TerminalTypeId
        toiletQuery.setTerminalTypeId(romaConf.getTerminalTypeId());
        toiletQuery.setPageSize(50);
        toiletQuery.setPageNo(pageNo);
        while (true) {
            toiletQuery.setPageNo(pageNo);
            try {
                // 拿到盥洗室属性数据
                String toiletRecord = this.getToiletRecord(toiletQuery);
                ToiletResultBody toiletResultBody = JSONObject.parseObject(toiletRecord, ToiletResultBody.class);
                log.info("======================================roma请求盥洗室属性结果=========================================={}", toiletResultBody.getCode());
                if (toiletResultBody.getCode().intValue() == 200) {
                    List<ToiletList> toiletList = toiletResultBody.getData().getList();
                    list.addAll(toiletList);
                    if (pageNo * toiletResultBody.getData().getPageSize() < toiletResultBody.getData().getTotalCount()) {
                        pageNo++;
                    } else {
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        log.info("盥洗室数据拉取长度==================================={}", list.size());
        // 拿到所有盥洗室属性数据list
        if (!CollectionUtils.isEmpty(list)) {
            // 根据厂商“华为-roma”拿到事件类型 code:alarmInventoryCode
            Map<String, String> entries = redisTemplate.opsForHash().entries(RedisUtils.format(21));
            // 第三方设备换取设备中台id
            DevicePageQuery devicePageQuery = new DevicePageQuery();
            devicePageQuery.setThirdDeviceIdList(list.stream().map(ToiletList::getTerminalId).map(Objects::toString).collect(Collectors.toList()));
            List<DeviceDTO> deviceList = deviceCentService.listDevice(null, devicePageQuery);
            Map<String, List<DeviceDTO>> map = deviceList.stream().collect(Collectors.groupingBy(DeviceDTO::getThirdDeviceId));
            for (ToiletList toiletList : list) {
                List<ToiletPropertys> propertys = toiletList.getPropertys();
                if (!CollectionUtils.isEmpty(propertys)) {
                    for (ToiletPropertys property : propertys) {
                        if (null != entries.get(property.getPropertyCode())) {
                            List<DeviceDTO> deviceDTOList = map.get(toiletList.getTerminalId().toString());
                            if (CollectionUtils.isEmpty(deviceDTOList)) {
                                continue;
                            } else {
                                AlarmManagement alarmManagement = new AlarmManagement();
                                alarmManagement.setProjectId(projectId);
                                alarmManagement.setDeviceId(deviceDTOList.get(0).getId());
                                alarmManagement.setAlarmInventoryCode(entries.get(property.getPropertyCode()));
                                alarmManagement.setAlarmTime(new Date());
                                try {
                                    BigDecimal propertyValue = new BigDecimal(property.getPropertyValue());
                                    alarmManagement.setThreshold(propertyValue);
                                } catch (Exception e) {
                                    continue;
                                }
                                // 空气质量类型且propertyIsAlarm:true进行告警
                                if (property.getPropertyCode().equals("airQualityLevel")) {
                                    if (property.getPropertyIsAlarm()) {
                                        log.info("===============空气质量告警源数据======================{}", property);
                                        // 定义告警推送模板，topic：AlarmConstant.ROMA_TOPIC
                                        generalProducer.send(AlarmConstant.ROMA_TOPIC, alarmManagement);
                                    }
                                } else {
                                    log.info("===============其他告警源数据======================{}", property);
                                    // 定义告警推送模板，topic：AlarmConstant.ROMA_TOPIC
                                    alarmManagement.setContent(property.getPropertyName() + "告警，当前" + property.getPropertyName() + "为" + property.getPropertyValue());
                                    generalProducer.send(AlarmConstant.ROMA_TOPIC, alarmManagement);
                                }
                            }
                        }
                    }
                }
            }
        }
        log.info("==================================盥洗室推送告警执行完成=============================================");
        return ResultJson.success();
    }

}
